/*
 * You can use as following code:
 *
 * In your C/C++ file, enable/disable LOG_ENABLE macro, and then include this
 * header file.
 *
 * #define LOG_TAG           "MOD_TAG"
 * #define LOG_LVL           LOG_LEVEL_INFO
 * #include <xlog.h>          // must after of LOG_LVL, LOG_TAG or other options
 *
 * Then in your C/C++ file, you can use LOG_X macro to print out logs:
 * LOG_D("this is a debug log!");
 * LOG_E("this is a error log!");
 */
#ifndef _XLOG_H_
#define _XLOG_H_

#include <stdint.h>

#define LOG_ENABLE
#define LOG_ENABLE_COLOR
#define LOG_ENABLE_TICK    // 需要同时打开LOG_ENABLE_COLOR，后面再


#ifdef LOG_TAG
    #ifndef DBG_SECTION_NAME
        #define DBG_SECTION_NAME    LOG_TAG
    #endif
#else
    /* compatible with old version */
    #ifndef DBG_SECTION_NAME
        #define DBG_SECTION_NAME    "NO_TAG"
    #endif
#endif /* LOG_TAG */

// typedef enum
// {
//     LOG_LEVEL_NONE     = 0,
//     LOG_LEVEL_ERROR    = 1,
//     LOG_LEVEL_WARN     = 2,
//     LOG_LEVEL_INFO     = 3,
//     LOG_LEVEL_DEBUG    = 4,
//     LOG_LEVEL_VERBOSE  = 5,
//     LOG_LEVEL_MAX
// }log_level_t;

// 级别需要用#define定义，使用enum会使级别配置#if判断失效！！
#define LOG_LEVEL_NONE     0
#define LOG_LEVEL_ERROR    1
#define LOG_LEVEL_WARN     2
#define LOG_LEVEL_INFO     3
#define LOG_LEVEL_DEBUG    4
#define LOG_LEVEL_VERBOSE  5

#ifdef LOG_ENABLE

    #ifdef LOG_LVL
        #ifndef LOG_LEVEL
        #define LOG_LEVEL         LOG_LVL
        #endif
    #else
        /* compatible with old version */
        #ifndef LOG_LEVEL
        #define LOG_LEVEL         LOG_LEVEL_WARN
        #endif
    #endif /* LOG_LVL */

    /*
    * The color for terminal (foreground)
    * BLACK    30
    * RED      31
    * GREEN    32
    * YELLOW   33
    * BLUE     34
    * PURPLE   35
    * CYAN     36
    * WHITE    37
    */
    
    #ifdef LOG_ENABLE_COLOR
        #ifdef LOG_ENABLE_TICK
            #include "bsp_systick.h"
            #define _DBG_LOG_HDR(lvl_name, color_n)                    \
                printf("\033["#color_n"m[%d][" lvl_name "/" DBG_SECTION_NAME "] ", GetTickCount())
        #else
            #define _DBG_LOG_HDR(lvl_name, color_n)                    \
                printf("\033["#color_n"m[" lvl_name "/" DBG_SECTION_NAME "] ")
        #endif
        #define _DBG_LOG_X_END                                     \
            printf("\033[0m\r\n")
    #else
        #ifdef LOG_ENABLE_TICK
            #include "bsp_systick.h"
            #define _DBG_LOG_HDR(lvl_name, color_n)                    \
            printf("[%d][" lvl_name "/" DBG_SECTION_NAME "] ", GetTickCount())
        #else
            #define _DBG_LOG_HDR(lvl_name, color_n)                    \
            printf("[" lvl_name "/" DBG_SECTION_NAME "] ")
        #endif
        #define _DBG_LOG_X_END                                     \
            printf("\n")
    #endif /* LOG_ENABLE_COLOR */


    #define dbg_log_line(lvl, color_n, fmt, ...)                \
        do                                                      \
        {                                                       \
            _DBG_LOG_HDR(lvl, color_n);                         \
            printf(fmt, ##__VA_ARGS__);                     \
            _DBG_LOG_X_END;                                     \
        }                                                       \
        while (0)


#else
    #define dbg_log_line(lvl, color_n, fmt, ...)
#endif /* LOG_ENABLE */

#if (LOG_LEVEL >= LOG_LEVEL_VERBOSE)
#define LOG_V(fmt, ...)      dbg_log_line("V", 0, fmt, ##__VA_ARGS__)
#else
#define LOG_V(...)
#endif

#if (LOG_LEVEL >= LOG_LEVEL_DEBUG)
    #define LOG_D(fmt, ...)      dbg_log_line("D", 0, fmt, ##__VA_ARGS__)

    void log_hexdump(const char *tag, uint32_t width, uint8_t *buf, uint32_t size);
    // size超过32会溢出，暂未解决
    // eg: LOG_HEX("receive", 16, buffer, 10);
    #define LOG_HEX(tag, width, buf, size)      log_hexdump(tag, width, buf, size)
#else
#define LOG_D(...)
#define LOG_HEX(name, width, buf, size)
#endif

#if (LOG_LEVEL >= LOG_LEVEL_INFO)
#define LOG_I(fmt, ...)      dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
#else
#define LOG_I(...)
#endif

#if (LOG_LEVEL >= LOG_LEVEL_WARN)
#define LOG_W(fmt, ...)      dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
#else
#define LOG_W(...)
#endif

#if (LOG_LEVEL >= LOG_LEVEL_ERROR)
#define LOG_E(fmt, ...)      dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
#else
#define LOG_E(...)
#endif


#endif

